<template>
  <el-dialog v-model="isShow" @closed="emits('cancelIssue')">
    <h1 class="title">文章发布</h1>
    <el-form :model="formData" label-width="80px">
      <el-form-item label="分类:">
        <el-radio-group v-model="formData.type" type="small">
          <template v-for="_type in types">
            <el-radio-button :label="_type" />
          </template>
        </el-radio-group>
      </el-form-item>
      <el-form-item label="标签:">
        <el-select
          v-model="formData.tags"
          placeholder="标签选择 至多3个"
          filterable
          :style="{
            width: '300px',
            marginRight: '10px'
          }"
          multiple
          :multiple-limit="3"
        >
          <el-option
            v-for="item in tags"
            :key="item.value"
            :value="item.value"
          />
        </el-select>
        <el-button v-if="!editAddTagFlag" @click="editClick">
          添加标签
        </el-button>
        <el-input
          :style="{
            maxWidth: '150px'
          }"
          placeholder="按下回车键添加标签"
          ref="editInput"
          v-else
          v-model="addTagContent.tagName"
          @blur="inputBlur"
        />
      </el-form-item>
      <el-form-item label="封面:">
        <el-upload
          class="avatar-uploader"
          action="http://lianghj.top:9999/blog/image"
          :before-upload="beforeAvatarUpload"
          :on-success="handleAvatarSuccess"
          :headers="{
            authorization: `Bearer ${userStore.userInfo?.token}`,
            id: userStore.userInfo?.id
          }"
          :show-file-list="false"
          :data="{ id: userStore.userInfo?.id }"
        >
          <img
            v-if="formData.cover"
            v-lazy="formData.cover"
            class="avatar"
            alt=""
          />
          <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
        </el-upload>
      </el-form-item>
      <el-form-item label="文章简要:">
        <el-input
          maxlength="150"
          v-model="formData.desc"
          :rows="5"
          type="textarea"
        />
      </el-form-item>
    </el-form>
    <template #footer>
      <el-button @click="emits('cancelIssue')">取消</el-button>
      <el-button type="primary" @click="postArticleClick">确定并发布</el-button>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import { onMounted, reactive, ref, watch, nextTick } from "vue";
import { useRoute } from "vue-router";
import { ElMessage } from "element-plus";
import { Plus } from "@element-plus/icons-vue";

// 发送网络请求
import {
  getArticleTagsService,
  addTagService,
  createArticleService,
  udpateArticle
} from "@/service/article";
import { getUserInfoByID } from "@/service/user";

import router from "@/router";
import user from "@/store/user";
// 静态配置
import type { UploadProps } from "element-plus";

import { types } from "./config";
import { IUserState } from "@/store";
import local from "@/utils/local";
import { bgArr } from "@/utils/config";
// 发送事件
const emits = defineEmits(["cancelIssue"]);
// 定义发送事件
// 定义props接收文章的标题和内容
const props = defineProps<{
  title?: string;
  content?: string;
  show: boolean;
}>();
// 提交的表单数据
const formData = reactive<{
  type: string;
  tags: string[];
  desc: string;
  cover: string;
}>({
  type: "",
  tags: [],
  desc: "",
  cover: ""
});
interface SelectItem {
  label: string;
  value: string;
}
const route = useRoute();
// 用户信息
const userStore: IUserState = user();
// 获取的所有标签
const tags = ref<SelectItem[]>([]);
// 显示和隐藏
const isShow = ref(false);
// 添加添加标签
const editAddTagFlag = ref(false);
// 输入框元素
const editInput = ref<HTMLInputElement>();
// 添加标签的存储
const addTagContent = reactive({
  tagName: "",
  uid: 0
});

// 上传图片成功
const handleAvatarSuccess: UploadProps["onSuccess"] = (
  response,
  uploadFile
) => {
  if (response.data.msg) {
    local.clear();
    router.push("/");
    window.location.replace("/");
    return ElMessage({
      type: "error",
      message: "登录Token失效!请重新登录~"
    });
  }
  formData.cover = response.data.cover;
};

// 2. 添加标签
// 2.1 编辑标签事件 & 获取焦点 & 绑定键盘按下事件
const addTag = async (event: KeyboardEvent) => {
  if (event.code === "Enter") {
    if (!addTagContent.tagName.length) {
      return Toast("标签的内容不能为空!", "warning");
    } else {
      const flag = tags.value.findIndex(
        item => item.value.toLowerCase() === addTagContent.tagName.toLowerCase()
      );
      if (flag !== -1) {
        // 判断标签是否已存在
        return Toast(`${addTagContent.tagName} 标签已存在`, "warning");
      }
      addTagContent.uid = userStore.userInfo?.id as number;
      const addTagResult: any = await addTagService(addTagContent);
      // 添加标签返回成功的响应码
      if (addTagResult.code === 0) {
        // 获取标签
        initGetTags();
        editAddTagFlag.value = false;
        if (formData.tags.length <= 4) {
          formData.tags.push(addTagContent.tagName as string);
        }
        addTagContent.tagName = "";
        return Toast("标签添加成功!", "success");
      } else {
        // 失败
        return Toast(addTagResult.data.msg, "error");
      }
    }
  }
};
// 2.2 添加标签按钮点击事件
const editClick = () => {
  editAddTagFlag.value = true;
  nextTick(() => {
    // 元素更新完成获取输入框焦点
    editInput.value?.focus();
  });
  // 添加键盘按下事件,以便添加标签
  window.addEventListener("keydown", addTag);
};
// 2.3 添加标签的输入框失去焦点
const inputBlur = () => {
  editAddTagFlag.value = false;
  // 失去焦点移除事件
  window.removeEventListener("keydown", addTag);
};
// 初始化获取所有的标签
const initGetTags = async () => {
  const res: any = await getArticleTagsService();
  // 处理options标签渲染格式
  tags.value = res.data.map((item: any) => {
    return {
      value: item.tag,
      label: item.tag
    };
  });
};
// 3. 发布文章
const postArticleClick = async () => {
  if (route.path === "/writearticle") {
    if (!props.title || !props.content) {
      return Toast("内容和标题不能为空!", "error");
    }
    if (!formData.type) {
      return Toast("分型不能为空!", "error");
    }
    if (!formData.tags.length) {
      return Toast("标签至少选择一个!", "error");
    }
    if (!formData.desc) {
      formData.desc = "作者很懒什么也没有写~~";
    }
    if (!formData.cover) {
      formData.cover = bgArr[Math.floor(Math.random() * bgArr.length + 1)];
    }
    const res: any = await createArticleService({
      ...formData,
      title: props.title,
      content: props.content
    });
    if (res.code === 0) {
      const userinfo: any = await getUserInfoByID(
        userStore.userInfo?.id as number
      );
      userStore.userInfo = {
        ...userStore.userInfo,
        ...userinfo.data,
        token: userStore.userInfo?.token
      };
      router.push("/");
      return Toast("发布文章成功", "success");
    } else {
      return Toast(res.data.msg, "error");
    }
  } else {
    console.log("编辑文章");
    const article = local.get("edit-article");
    const res: any = await udpateArticle({
      ...article,
      ...formData,
      title: props.title!,
      content: props.content!
    });
    if (res.code === 0) {
      Toast(res.data.msg, "success");
      router.go(-1);
    }
    console.log(res, "res");
  }
};
// 信息发送函数封装
const Toast = (
  message: string,
  type: "info" | "success" | "warning" | "error"
) => {
  ElMessage({
    message,
    type
  });
};

const beforeAvatarUpload: UploadProps["beforeUpload"] = rawFile => {
  if (rawFile.size / 1024 / 1024 > 2) {
    ElMessage.error("图片大小不能超过2M!");
    return false;
  }
  return true;
};

// 属性监测钩子
watch(
  () => props.show,
  () => {
    isShow.value = props.show;
  },
  {
    deep: true
  }
);
// 挂载完成钩子
onMounted(() => {
  initGetTags();
  const res = local.get("edit-article");
  if (res) {
    formData.tags = res.tags;
    formData.type = res.type;
    formData.cover = res.cover;
    formData.desc = res.desc;
  }
});
</script>

<style scoped lang="less">
.title {
  margin-bottom: 10px;
}
</style>
